package com.wangyadong.hobby.schedule.jobtask.tree.example1;

import com.wangyadong.hobby.schedule.jobtask.tree.Position;

import java.util.Iterator;

public class LinkedListBinaryTree<E> extends AbstractBinaryTree<E> {

    private static class Node<E> implements Position<E> {

        private E element;
        private Node left;
        private Node right;
        private Node parent;

        public Node() {
        }


        public Node(E e, Node left, Node right, Node parent) {
            this.left = left;
            this.right = right;
            this.parent = parent;
            this.element = e;
        }

        public Node getLeft() {
            return left;
        }

        public void setLeft(Node left) {
            this.left = left;
        }

        public Node getRight() {
            return right;
        }

        public void setRight(Node right) {
            this.right = right;
        }

        public Node getParent() {
            return parent;
        }

        public void setParent(Node parent) {
            this.parent = parent;
        }

        @Override
        public E getElement() throws IllegalStateException {
            return element;
        }

        public void setElement(E e) {
            this.element = e;
        }
    }

    private int size = 0;
    protected Node<E> root = null;

    public LinkedListBinaryTree() {
    }

    protected Node<E> createNode(E e, Node left, Node right, Node parent) {
        return new Node<E>(e, left, right, parent);
    }

    /***
     * 节点验证
     * @param position
     * @return
     * @throws IllegalArgumentException
     */
    private Node<E> validate(Position position) throws IllegalArgumentException {
        if (!(position instanceof Node)) {
            throw new IllegalArgumentException("type is invalidate");
        }
        Node node = (Node) position;

        return node;
    }

    public int size() {
        return size;
    }

    public Position root() {
        return root;
    }


    @Override
    public Position parent(Position position) throws IllegalArgumentException {
        Node<E> validate = validate(position);
        return validate.getParent();
    }

    @Override
    public Position left(Position position) throws IllegalArgumentException {
        Node<E> validate = validate(position);
        return validate.getLeft();
    }

    @Override
    public Position right(Position position) throws IllegalArgumentException {
        Node<E> validate = validate(position);
        return validate.getRight();
    }

    public Position addRoot(E element) throws IllegalStateException {
        if (!isEmpty())
            throw new IllegalStateException("is not empty");
        root = createNode(element, null, null, null);
        size = 1;
        return root;
    }

    public Position<E> addLeft(E element, Position position) throws IllegalArgumentException {
        Node<E> parent = validate(position);
        if (parent.getLeft() != null) {
            throw new IllegalArgumentException("");
        }
        Node<E> node = createNode(element, null, null, parent);
        parent.setLeft(node);
        size++;
        return node;
    }

    public Position addRight(E element, Position position) throws IllegalArgumentException {
        Node<E> validate = validate(position);
        if (validate.getRight() != null) {
            throw new IllegalArgumentException("");
        }
        Node<E> node = createNode(element, null, validate, null);
        size++;
        validate.setRight(node);
        return node;
    }


    public Node remove1(Position position) throws IllegalArgumentException {
        Node<E> node = validate(position);
        if (childNum(position) == 2) {
            throw new IllegalArgumentException("");
        }
        Node child = node.getLeft() != null ? node.getLeft() : node.getRight();
        Node parent = node.getParent();
        if (child != null) {
            child.setParent(parent);
        }
        if (node == root()) {
            node = child;
        } else {
            if (left(position) != null) {
                parent.setLeft(child);
            } else {
                parent.setRight(child);
            }
        }

        size--;
        node.setParent(node);
        node.setLeft(null);
        node.setRight(null);
        node.setElement(null);
        return node;
    }

    @Override
    public Iterable<Position> position(Position position) throws IllegalArgumentException {
        return null;
    }

    @Override
    public Iterator iterator() {
        return null;
    }

    @Override
    public boolean isRoot(Position position) throws IllegalArgumentException {
        return false;
    }

    public static void main(String[] args) {
        LinkedListBinaryTree<String> listBinaryTree = new LinkedListBinaryTree<>();
        listBinaryTree.addRoot("root");
        listBinaryTree.addLeft("sub-left-1", listBinaryTree.root());
        listBinaryTree.addRight("sub-right-1", listBinaryTree.root());
        listBinaryTree.remove1(listBinaryTree.left(listBinaryTree.root()));
        System.out.println("==============================================");
    }
}
